#include "modem.h"

/**
 * setup_device()
 * responsible for opening modem device and
 * preparing device settings for first use.
 */
int setup_device(char * name, int * fd)
{
	struct termios tio;
	*fd = open(name, O_RDWR | O_NDELAY | O_NOCTTY);
	if (*fd < 0)
	{
		printf("ERROR: COULD NOT OPEN DEVICE\n");
		return -1;
	}
	fcntl(*fd, F_SETFL, 0);
	if (tcgetattr(*fd, &tio) !=0)
	{
		printf("ERROR: COULD NOT GET DEVICE ATTRIBUTES\n");
		return -1;
	}
	//Now that the devices current state is set in tio, we can manually change it...
	//printf("%d\n",*fd);
	tio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
//	tio.c_iflag &= ~(ISTRIP | INLCR );
	tio.c_oflag &= ~(OPOST);
	tio.c_cflag &= ~CSIZE;
	tio.c_cflag &= ~CSTOPB;
	tio.c_cflag &= ~PARENB;
	tio.c_cflag |= (CS8 | CLOCAL | CREAD);
	tio.c_cc[VMIN] = 0;
	tio.c_cc[VTIME] = 10;

	if (cfsetspeed(&tio, B9600) < 0 )
	{
		printf("COULD NOT SET SPEED\n");
		return -1;
	}
	//printf("Set speed correctly.\n");
	if (tcsetattr(*fd, TCSAFLUSH, &tio) != 0)
	{
		printf("Could not set attributes\n");
		return -1;
	}
	tcflush(*fd, TCIOFLUSH);
	//printf("Setup complete!\n"); 
	return 0;

}

/**
 * disconnect()
 * Responsible for closing connections, if they exist.
 */
int disconnect(int fd)
{
	//Send the escape sequence. Assume we're connected.
	send_device(fd,"+++");
	wait_for_signal(fd,"OK",-2);
	send_device(fd,"ATH\r");
	return 0;
}

/**
 * send_device()
 * Responsible for sending data over the connection on specified device.
 */
int send_device(int fd, char * str)
{
	//printf("Sending %s to %d\n",str,fd);
	write(fd, str, strlen(str));
	return 0;
}

/**
 * read_device()
 * Responsible for reading data sent to the specied device.
 */
int read_device(int fd, char **strptr)
{
	char * str = *strptr;
	if (str != NULL)
	{
		free(str);
		str = NULL;
	}
	int len = 0;
	//Check with ioctl if there is stuff to read.
	int result = ioctl(fd, FIONREAD, &len);
//	//printf("IOCTL value:%d\n", result);
	USLEEP(100000);
	if (result != -1)
	{
		str = (char *)malloc(len+1);
		read(fd,str,len);
		str[len] = '\0';
	//	if (len != 0 )
			//printf("%s", str);
		*strptr  = str;
		return len;
	}
	
	return -1;
}

/**
 * close_device()
 * Responsibl for closing the device, assume that connections have
 * already been terminated.
 */
int close_device(int * fd)
{
	close(*fd);
	return 0;
}

/**
 * trim()
 * A utility function for removing leading and trailing garbage in a string.
 */
char* trim(char ** strptr)
{
	char * str = *strptr;
	int i = 0;
	int j = strlen(str) - 2;
	char * strn;
	//Iterate backwards to the first line ending or position 0. This is the starting position.
	for (i = j; (i > 0) && (str[i] != '\n'); i--);
	//Now, iterate forwards again, stopping when we get to something that isn't a space.
	for (; (i < j)&&(isspace(str[i])); i++);
	//Start at the back, stop when we get to text.
	for (; (j >= 0) && (isspace(str[j])); j--);
	//Allocate just enough memory.
	strn = (char *)malloc(j-i + 2);
	//Copy the section of the string we want to the new string.
	strncpy(strn,str+i,(j-i)+1);
	//Make sure we're ending with \0.
	strn[j-i+1] = '\0';
	free(str);
	str = NULL;
	*strptr = strn;
	return 0;
}

/**
 * wait_for_signal()
 */
int wait_for_signal(int fd, char * signal, int max_retries)
{
	char * buffer = NULL;
	int i = max_retries;
	//If max_retries is negative, loop until the signal is reached.
	for (; (i >= 0) || (max_retries < 0); i--)
	{
		if (read_device(fd, &buffer) > 0)
		{
			trim(&buffer);
			//printf("%s\n", buffer);
			//printf("%d\n", strncmp(buffer,signal,strlen(signal)));
			if (strncmp(buffer,signal,strlen(signal)-1) == 0 )
			{
				free(buffer);
				buffer = NULL;
				return 0;
			}
		}
		USLEEP(100);
	}
	if (buffer != NULL)
		free(buffer);
		buffer = NULL;
	return -1;
}
